/*
 * The contents of this web application are subject to the Mozilla Public License Version 
 * 1.1 (the "License"); you may not use this web application except in compliance with 
 * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 * for the specific language governing rights and limitations under the License.
 * 
 * The Original Code is owned by and the Initial Developer of the Original Code is 
 * Composite A/S (Danish business reg.no. 21744409). All Rights Reserved
 * 
 * Section 11 of the License is EXPRESSLY amended to include a provision stating 
 * that any dispute, including but not limited to disputes related to the enforcement 
 * of the License, to which Composite A/S as owner of the Original Code, as Initial 
 * Developer or in any other role, becomes a part to shall be governed by Danish law 
 * and be initiated before the Copenhagen City Court ("K�benhavns Byret")            
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;
using Composite.Data;
using Composite.Data.Plugins.DataProvider;
using Composite.Plugins.Data.DataProviders.MSSqlServerDataProvider.CodeGeneration;
using Composite.Plugins.Data.DataProviders.MSSqlServerDataProvider.Foundation;


namespace Composite.Plugins.Data.DataProviders.MSSqlServerDataProvider
{
    internal sealed class SqlDataTypeStore
    {
        private readonly SqlDataTypeStoresContainer _sqlDataTypeStoresContainer;
        private Type _listOfInterfaceType = null;


        internal SqlDataTypeStore(Type interfaceType, Dictionary<SqlDataTypeStoreTableKey, SqlDataTypeStoreTable> sqlDataTypeStoreTables, bool isGeneretedDataType, SqlDataTypeStoresContainer sqlDataTypeStoresContainer)
        {
            _sqlDataTypeStoresContainer = sqlDataTypeStoresContainer;

            InterfaceType = interfaceType;
            StoreTables = sqlDataTypeStoreTables;
            IsGeneretedDataType = isGeneretedDataType;
        }

                
        public Type InterfaceType { get; private set; }


        public bool IsGeneretedDataType { get; private set; }

        
        internal Dictionary<SqlDataTypeStoreTableKey, SqlDataTypeStoreTable> StoreTables { get; private set; }

        
        public IQueryable GetQueryable()
        {
            SqlDataTypeStoreTableKey tableKey = GetTableKey();
                

            IQueryable queryable;
            if (StoreTables.ContainsKey(tableKey))
            {
                queryable = SqlDataContextHelperClass.GetTable(_sqlDataTypeStoresContainer.GetDataContext(), StoreTables[tableKey]);
            }
            else
            {
                if (_listOfInterfaceType == null)
                {
                    _listOfInterfaceType = typeof(List<>);
                    _listOfInterfaceType = _listOfInterfaceType.MakeGenericType(InterfaceType);
                }

                IEnumerable list = (IEnumerable)Activator.CreateInstance(_listOfInterfaceType, null);

                return list.AsQueryable();
            }


            return queryable;
        }


       
        public IData GetDataByDataId(IDataId dataId, DataProviderContext dataProivderContext)
        {
            SqlDataTypeStoreTable storage = GetCurrentTable();

            return storage.SqlDataProviderHelper.GetDataById(GetQueryable(), dataId, dataProivderContext);
        }


        
        public IData AddNew(IData dataToAdd, DataProviderContext dataProivderContext, DataContext dataContext)
        {
            SqlDataTypeStoreTable storeTable = GetCurrentTable();

            return storeTable.SqlDataProviderHelper.AddData((ISqlDataContext)dataContext, dataToAdd, dataProivderContext);
        }



        public void RemoveData(IData dataToRemove, DataContext dataContext)
        {
            SqlDataTypeStoreTable storeTable = GetCurrentTable();

            storeTable.SqlDataProviderHelper.RemoveData((ISqlDataContext)dataContext, dataToRemove);
        }



        private SqlDataTypeStoreTableKey GetTableKey()
        {
            string dataScope = DataScopeManager.MapByType(InterfaceType).Name;
            string cultureInfo = LocalizationScopeManager.MapByType(InterfaceType).Name;

            return new SqlDataTypeStoreTableKey(dataScope, cultureInfo);
        }



        private SqlDataTypeStoreTable GetCurrentTable()
        {
            SqlDataTypeStoreTableKey tableKey = GetTableKey();

            if (StoreTables.ContainsKey(tableKey) == false) throw new InvalidOperationException(string.Format("No SQL table defined for the interface type '{0}' in the data scope '{1}' and locale '{2}'", InterfaceType.FullName, tableKey.DataScopeIdentifierName, tableKey.LocaleCultureName));

            return StoreTables[tableKey];
        }
    }
}
